import os
import sys
import warnings

import pandas as pd
import numpy as np

sys.path.append('..')
warnings.filterwarnings('ignore')

from tools.setting import DATA_DIR
from tools.common_var import STABLE_COINS_MARKETCAP

ANALYSIS_DATA_DIR = os.path.join(DATA_DIR, 'analysis')
os.makedirs(ANALYSIS_DATA_DIR, exist_ok=True)


def btc_price_analysis():
    # 读取BTC_数据
    data = pd.read_csv('E:\\data\\ohlcvm_data\\daily\\bitcoin.csv', index_col='end_date')
    data.rename(columns={'close': 'close_cmc'}, inplace=True)
    kline = pd.read_csv('E:\\data\\ohlcvm_data\\kline\\BTC_24h.csv', index_col='end_date')
    kline.drop_duplicates(inplace=True)
    df = pd.concat([data, kline], axis=1).fillna(method='ffill')
    data = df.loc[data.index]

    # 对数价格
    data['log_prices'] = np.log10(data['close'])

    # 计算Close VWAP120 ratio, Close VWAP140 ratio
    volume_series = data['volume']
    weighted_close = data['close'].astype(float) * volume_series.astype(float)
    weighted_close.dropna(inplace=True)
    weighted_close_ma140 = weighted_close.rolling(window=140, min_periods=140).sum()
    weighted_close_ma120 = weighted_close.rolling(window=120, min_periods=120).sum()
    volume_series_ma140 = volume_series.rolling(window=140, min_periods=140).sum()
    volume_series_ma120 = volume_series.rolling(window=120, min_periods=120).sum()
    vwap140 = (weighted_close_ma140 / volume_series_ma140)
    vwap120 = (weighted_close_ma120 / volume_series_ma120)
    data['Close VWAP140 ratio'] = data['close'] / vwap140
    data['Close VWAP120 ratio'] = data['close'] / vwap120

    # 计算Close MA140 ratio， Close MA140 ratio
    data['ma140'] = data['close'].rolling(window=140, min_periods=140).mean()
    data['ma120'] = data['close'].rolling(window=120, min_periods=120).mean()
    data['Close MA140 ratio'] = data['close'] / data['ma140']
    data['Close MA120 ratio'] = data['close'] / data['ma120']

    # 计算BTC OSC
    column_list = ['close']
    for ma_period in [30, 60, 90, 120, 150, 200, 300]:
        data[f'ma_{ma_period}'] = data['close'].rolling(window=ma_period, min_periods=ma_period).mean()
        data[f'osc_{ma_period}'] = (data['close'] - data[f'ma_{ma_period}']) / data[f'ma_{ma_period}']
        column_list.append(f'osc_{ma_period}')

    # 计算Bitcoin Price Temperature
    # The Bitcoin Price Temperature (BPT) is an oscillator that models the number of standard deviations that price has moved away from the 4-yr moving average
    data['ma_1460'] = data['close'].rolling(window=1460, min_periods=1460).mean()
    data['std_1460'] = data['close'].rolling(window=1460, min_periods=1460).std()
    data['Bitcoin Price Temperature'] = (data['close'] - data['ma_1460']) / data['std_1460']

    # 计算Mayer Multiple
    # The Mayer Multiple is an oscillator calculated as the ratio between price, and the 200-day moving average.
    data['ma_200'] = data['close'].rolling(window=200, min_periods=200).mean()
    data['Mayer Multiple'] = data['close'] / data['ma_200']

    # 计算Stablecoin Supply Ratio (SSR)
    btc_marketcap = data['market_cap']
    # 获取稳定币市值数据
    mc_list = []
    for i in STABLE_COINS_MARKETCAP:
        mc = pd.read_csv(f'E:\\data\\ohlcvm_data\\daily\\{STABLE_COINS_MARKETCAP[i]}.csv', index_col='end_date')[
            'market_cap']
        mc.name = i
        mc_list.append(mc)
    stablecoin_marketcap = pd.concat(mc_list, axis=1)
    stablecoin_marketcap_sum = stablecoin_marketcap.sum(axis=1)
    data['DIY Stablecoin Supply Ratio (SSR)'] = btc_marketcap / stablecoin_marketcap_sum

    # 计算DIY Stablecoin Supply Ratio (SSR) Oscillator 120
    data['DIY Stablecoin Supply Ratio (SSR) Oscillator 120'] = (data['DIY Stablecoin Supply Ratio (SSR)'] - data[
        'DIY Stablecoin Supply Ratio (SSR)'].rolling(120).mean()) / data['DIY Stablecoin Supply Ratio (SSR)'].rolling(
        120).std()

    # 计算DIY Stablecoin Supply Ratio (SSR) Oscillator 140
    data['DIY Stablecoin Supply Ratio (SSR) Oscillator 140'] = (data['DIY Stablecoin Supply Ratio (SSR)'] - data[
        'DIY Stablecoin Supply Ratio (SSR)'].rolling(140).mean()) / data['DIY Stablecoin Supply Ratio (SSR)'].rolling(
        140).std()

    # 计算DIY Stablecoin Supply Ratio (SSR) Oscillator 200
    data['DIY Stablecoin Supply Ratio (SSR) Oscillator 200'] = (data['DIY Stablecoin Supply Ratio (SSR)'] - data[
        'DIY Stablecoin Supply Ratio (SSR)'].rolling(200).mean()) / data['DIY Stablecoin Supply Ratio (SSR)'].rolling(
        200).std()

    # 波动指标
    data['ret'] = data['close'].pct_change()
    data['pre_close'] = data['close'].shift(1)
    data['30days_cum_ret'] = data['close'].pct_change(30)
    data['amplitude'] = (data['high'] - data['low']) / data['pre_close']
    data['amplitude_ma30'] = data['amplitude'].rolling(30).mean()
    data['sign_amplitude'] = data['amplitude'] * np.sign(data['ret'])

    # 历史波动率
    for period in [30]:
        data[f'std_{period}days'] = data['ret'].rolling(period).std()
        for ma_period in [30, 60, 100, 120, 150]:
            data[f'std_{period}days_ma{ma_period}'] = data[f'std_{period}days'].rolling(ma_period).mean()
            data[f'std_{period}days_bias{ma_period}'] = data[f'std_{period}days'] - data[
                f'std_{period}days_ma{ma_period}']
            data[f'std_{period}days_osc{ma_period}'] = data[f'std_{period}days_bias{ma_period}'] / data[
                f'std_{period}days_ma{ma_period}']

    # 振幅大于某一阈值占比
    period = 30
    threshold = 0.05
    data[f'amplitude_{period}days_>{threshold}_numratio'] = (data['amplitude'] >= threshold).rolling(period).sum() / period
    for ma_period in [30, 60, 100, 120, 150]:
        data[f'amplitude_{period}days_>{threshold}_numratio_ma{ma_period}'] = data[
                    f'amplitude_{period}days_>{threshold}_numratio'].rolling(ma_period).mean()
        data[f'amplitude_{period}days_>{threshold}_numratio_bias{ma_period}'] = data[f'amplitude_{period}days_>{threshold}_numratio'] - data[f'amplitude_{period}days_>{threshold}_numratio_ma{ma_period}']
        data[f'amplitude_{period}days_>{threshold}_numratio_osc{ma_period}'] = data[f'amplitude_{period}days_>{threshold}_numratio_bias{ma_period}'] / data[ f'amplitude_{period}days_>{threshold}_numratio_ma{ma_period}']

    # 过去period天中收益率大于某一阈值占比
    data[f'ret_{period}days_>{threshold}_numratio'] = (data['ret'] >= threshold).rolling(period).sum() / period

    # 过去period天中上涨天数
    period = 60
    data[f'ret_{period}days_>=0_numratio'] = (data['ret'] >= 0).rolling(period).sum() / period

    # 创过去period天新高天数
    # for newhigh_period in [10, 15, 20, 30, 40, 60]:
    newhigh_period =15
    period = 30
    data[f'new{newhigh_period}high_{period}days_numratio'] = ((data['close'] - data['close'].rolling(newhigh_period).max()) == 0).rolling(period).sum() / period

    # 上涨同时放量的时候
    for period in [14]:
        data[f'{period}days_ret'] = (data['close'] - data['close'].rolling(period + 1).min()) / data['close'].rolling(period + 1).min()
        data[f'{period}days_volume_chg'] = (data['volume'] - data['volume'].rolling(period + 1).min()) / data['volume'].rolling(period + 1).min()
        data[f'{period}days_amount_chg'] = (data['amount'] - data['amount'].rolling(period + 1).min()) / data['amount'].rolling(period + 1).min()

        for ret_threshold in [0.3, 0.5]:
            for amount_threshold in [0.5, 0.8, 1]:
                if amount_threshold >= ret_threshold:
                    data[f'{period}days_ret_{ret_threshold}_amount_{amount_threshold}'] = 0
                    data.loc[(data[f'{period}days_ret'] >= ret_threshold) & (data[f'{period}days_amount_chg'] >= amount_threshold), f'{period}days_ret_{ret_threshold}_amount_{amount_threshold}'] = 1
                    data.loc[(data[f'{period}days_ret'] >= ret_threshold) & (data[f'{period}days_amount_chg'] >= amount_threshold), f'{period}days_ret_{ret_threshold}_amount_{amount_threshold}'] = 1

    file_name = os.path.join(ANALYSIS_DATA_DIR, f'btc_daily_price_analysis.csv')
    data.to_csv(file_name)


if __name__ == '__main__':
    btc_price_analysis()